#ifndef GEOMETRY_H
#define GEOMETRY_H

#include <vector>
#include "arithmetic.h"

class Polygon
{
private:
   std::vector<Point> hull;

   int y_scale(Point p1, Point p2, double sweep)
   {
      if(bounding_box(p1.y, p2.y, sweep, sweep))
      {
         if((p2.y == sweep) || (p1.y == sweep))
            return 0;
         return 1;
      }
      return -1;
   };


public:
   Polygon()
   {   };

   void add_point(Point p)
   {
      hull.push_back(p);
   };

   void enclose()
   {
      hull.push_back(hull[0]);
   };

   void break_line()
   {
      hull.pop_back();
   };

   int contains(Point p)
   {
      enclose();
      double sweep = p.y;
      int count = 0;
                 
      for(int i = 0; i < hull.size() - 1; i++)
      {
         Point a = hull[i], b = hull[i + 1];
         int sc = y_scale(a, b, sweep);
         if(sc >= 0)
         {
            bool box = bounding_box(a.x, b.x, p.x, p.x);
            int turn = left_turn(a, b, p);
            
            if((turn == 0) && (box == true))
               return 0;
            count += turn * (sc + 1) ;
         }
      }
      break_line();
      if(count == 0)
         return -1;
      return 1;
   };
};

class Polygon_with_holes
{
private:
   Polygon hull;
   std::vector<Polygon> holes;

public:
   Polygon_with_holes()
   {  };

   Polygon_with_holes(Polygon sp)
   {
      hull = sp;
   };

   void add_hole(Polygon hole)
   {
      holes.push_back(hole);
   };

   int contains(Point p)
   {
      int in_hull = hull.contains(p);
      if(in_hull <= 0)
         return in_hull;

      for(int i = 0; i < holes.size(); i++)
      {
         int in_hole = holes[i].contains(p);
         if(in_hole >= 0)
            return -in_hole;
      }
      return in_hull;
   };
};
#endif